﻿@using System.IO;
@using System.Text.Json;
@using System.Text.RegularExpressions;
@using simu485.Data
@inject ToastService ToastService;
@inject DialogService DialogService;

<style>
    .cell_mark {
        --bs-table-bg: lightyellow;
    }
</style>

<h5>@title</h5>

<div>
    <Table @ref="@ParamsTable" TItem="C485Param" OnQueryAsync="OnQueryAsync" PageItemsSource="@PageItemsSource"
           ShowPageInfo="false" IsPagination="true" ShowGotoNavigator="false" Height="890"
           IsBordered="true" AllowResizing="true" IsFixedHeader="true" 
           ClickToSelect="true" DoubleClickToEdit="true">
        @*  OnDoubleClickCellCallback="@OnDoubleClickCellCallback" Items="@Params.Take(Params.Count)" ScrollMode="ScrollMode.Virtual" *@
        <TableColumns>
            <TableColumn @bind-Field="@context.des" Text="参数描述" Align="Alignment.Center" Width="200" Readonly="true" OnCellRender="@OnCellRenderHandler" />
            <TableColumn @bind-Field="@context.value" Text="参数值" Align="Alignment.Center" OnCellRender="@OnCellRenderHandler" />
        </TableColumns>
    </Table>
</div>

@code {
    private static IEnumerable<int> PageItemsSource => new int[] {21};
    private async Task<QueryData<C485Param>> OnQueryAsync(QueryPageOptions options)
    {
        // await Task.Delay(200);
        IEnumerable<C485Param> items;
        items = Params.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems);
        return new QueryData<C485Param>()
            {
                Items = items,
                TotalCount = Params.Count
            };
    }


    private string title = "485 Parameters Table";

    public class C485Param
    {
        public string des { get; set; } = "";       // 参数描述
        public string value { get; set; } = "";     // 显示参数值
        public int type = 0;                        // 参数的类型。
        public int trace = 0;                       // 追踪修改的时间, 变化后10s内高亮显示。
    }
    public Table<C485Param>? ParamsTable { get; set; }     // table 控件
    public List<C485Param> Params { get; set; } = new();

    private C485Param CreateParam(string des, string value, int type = 1)
    {
        C485Param param = new();
        param.des = des;
        param.value = value;
        param.type = type;
        param.trace = -1000; // 初始化一个不会到达的负值1000s
        return param;
    }
    protected override void OnInitialized()
    {
        Params.Add(CreateParam("程序版本", "", 4));
        Params.Add(CreateParam("硬件版本", "", 4));
        Params.Add(CreateParam("厂家代码", "", 4));
        Params.Add(CreateParam("设备类型", "", 1));
        Params.Add(CreateParam("设备功能", "", 2));
        Params.Add(CreateParam("系统时间", "", 4));
        Params.Add(CreateParam("运行状态", "", 1));
        Params.Add(CreateParam("现在故障", "", 2));

        Params.Add(CreateParam("压缩机实时状态", "", 1));
        Params.Add(CreateParam("门状态", "", 1));
        Params.Add(CreateParam("灯状态", "", 1));
        Params.Add(CreateParam("功率值", "", 2));
        Params.Add(CreateParam("电池电压值", "", 1));
        Params.Add(CreateParam("联网状态", "00 12", 2));

        Params.Add(CreateParam("蒸发风机状态", "", 1));
        Params.Add(CreateParam("灯电流", "", 2));
        Params.Add(CreateParam("4G信号值", "1D", 1));

        Params.Add(CreateParam("库制冷/制热模式", "", 1));
        Params.Add(CreateParam("库设置温度", "", 1));
        Params.Add(CreateParam("库高温报警温度", "", 1));
        Params.Add(CreateParam("库低温报警温度", "", 1));
        Params.Add(CreateParam("库当前温度", "", 1));
        Params.Add(CreateParam("库设置温度下限", "", 1));
        Params.Add(CreateParam("库设置温度上限", "", 1));
        Params.Add(CreateParam("库温度上回差", "", 1));
        Params.Add(CreateParam("库温度下回差", "", 1));

        Params.Add(CreateParam("库传感器故障压缩机开机时间", "", 1));
        Params.Add(CreateParam("库传感器故障压缩机关机时间", "", 1));

        Params.Add(CreateParam("库温度补偿值", "", 1));
        Params.Add(CreateParam("库除霜周期/压缩机保护周期", "", 1));
        Params.Add(CreateParam("库除霜时间/压缩机保护时间", "", 1));
        Params.Add(CreateParam("库压缩机最小停机时间", "", 1));
        Params.Add(CreateParam("库环境温度", "", 1));
        Params.Add(CreateParam("库实际温度", "", 1));
        Params.Add(CreateParam("库本地控制状态", "", 1));

        Params.Add(CreateParam("开门次数", "", 3));
        Params.Add(CreateParam("客流次数", "", 3));

        base.OnInitialized();
    }

    public C485Param? GetParamByDes(string des)
    {
        foreach (C485Param param in Params)
        {
            if (param.des == des)
            { return param; }
        }
        return null;
    }

    private void SetValue(C485Param param, string value)
    {
        if (param.type == 4)
        {
            param.value = value;
            param.trace = 10000;
            return;
        }

        // byte by = 0;
        switch (param.des)
        {
            case "设备类型":
                param.value = value;
                break;
            case "现在故障":
                param.value = value;
                break;
            case "设备功能":
                param.value = value;
                break;

            case "运行状态":
            case "压缩机实时状态":
            case "门状态":
            case "灯状态":
            case "库本地控制状态":
            case "蒸发风机状态":
                param.value = value;
                break;

            case "库设置温度":
            case "库环境温度":
            case "库实际温度":
            case "库高温报警温度":
            case "库低温报警温度":
            case "库设置温度下限":
            case "库设置温度上限":
            case "库当前温度":
            case "库温度补偿值":
                param.value = (byte.Parse(value, System.Globalization.NumberStyles.HexNumber) - 100).ToString() + "℃";
                break;
            case "库温度上回差":
            case "库温度下回差":
                param.value = byte.Parse(value, System.Globalization.NumberStyles.HexNumber).ToString();
                break;

            case "开门次数":
            case "客流次数":
                param.value = int.Parse(value.Replace(" ", ""), System.Globalization.NumberStyles.HexNumber).ToString();
                break;

            case "库传感器故障压缩机开机时间":
            case "库传感器故障压缩机关机时间":
            case "库除霜时间/压缩机保护时间":
            case "库压缩机最小停机时间":
                param.value = byte.Parse(value, System.Globalization.NumberStyles.HexNumber).ToString() + "分钟";
                break;

            case "库除霜周期/压缩机保护周期":
                param.value = byte.Parse(value, System.Globalization.NumberStyles.HexNumber).ToString() + "小时";
                break;

            case "功率值":
            case "电池电压值":
            case "联网状态":
            case "4G信号值":
            case "灯电流":
            case "信号值":
            case "库制冷/制热模式":
                // TODO 暂时不需要处理的
                param.value = value;
                break;
        }
        param.trace = 10000;
    }

    private bool state_has_changed = false;
    private int start_index = -1;
    public string SetValueByDes(string des, string value, int value_type)
    {
        try
        {
            for (start_index = 0; start_index < Params.Count(); start_index++)
            //foreach (C485Param param in Params)
            {
                C485Param param = Params[start_index];
                if (param.des == des)
                {
                    if (param.type != value_type) return "收到指令类型-错误";
                    SetValue(param, value);
                    state_has_changed = true;
                    return "成功";
                }
            }
            start_index = -1;
            return "收到未知指令-错误";
        }
        catch(Exception e)
        {
            start_index = -1;
            return "收到指令值解析-错误";
        }
    }

    public string SetValueDismissFault(string value, int value_type)
    {
        for (start_index = 0; start_index < Params.Count(); start_index++)
        //foreach (C485Param param in Params)
        {
            C485Param param = Params[start_index];
            if (param.des == "现在故障")
            {
                if (param.type != value_type) return "收到指令类型-错误";
                ushort v_new = 0;
                if (!ushort.TryParse(value.Replace(" ", ""), System.Globalization.NumberStyles.HexNumber, null, out v_new))
                    return "收到数据-错误";
                ushort v_old = 0; 
                if (!ushort.TryParse(param.value.Replace(" ", ""), System.Globalization.NumberStyles.HexNumber, null, out v_old))
                    return "内部数据-错误";
                v_new = (ushort)(v_old & (~v_new));
                value = $"{(byte)(v_new << 8):X02}{(byte)v_new:X02}";
                SetValue(param, value);
                state_has_changed = true;
                return "成功";
            }
        }
        start_index = -1;
        return "收到未知指令-错误";
    }
    public void NotifyStateHasChanged()
    {
        InvokeAsync(StateHasChanged);
    }

    // public string GetValuesByCmd(ushort cmd)
    // {
    //     foreach (C485Param item in Params)
    //     {
    //         if (item.cmd1 == cmd || item.cmd2 == cmd) 
    //             return item.value;
    //     }

    //     return "";
    // }

    // public void SetValuesByCmd(ushort cmd, string value)
    // {
    //     foreach (C485Param item in Params)
    //     {
    //         if (item.cmd1 == cmd || item.cmd2 == cmd)
    //         {
    //             item.value = value;
    //             item.trace = 10000; // 10s
    //             return;
    //         }
    //     }
    // }

    // 父组件周期调用，更新数据
    public async Task Update()
    {
        //int cnt = DevProfiles.pms_name.Count();
        // modified_idx = cnt; // clear modified data index
        foreach (C485Param item in Params)
        {
            if (item.trace > 0)
                item.trace -= 50;
            else if (item.trace == 0) // 要触发变化从高亮状态恢复回来
                state_has_changed = true;
        }
        if (state_has_changed)
        {
            state_has_changed = false;

            if (start_index >= 0)
            {
                await ParamsTable!.QueryAsync(start_index / ParamsTable.PageItems + 1);
                start_index = -1;
            }

            await InvokeAsync(StateHasChanged);
        }

    }

    // 数据变化, mark背景黄色10s以作提示
    private static void OnCellRenderHandler(TableCellArgs args)
    {
        if (args.Row is C485Param item)
        {
            if (item.trace > 0)
            {
                if (args.ColumnName == "des")
                    args.Value = $"{item.des}";
                else if (args.ColumnName == "value")
                    args.Value = $"{item.value}";
                args.Class = "cell_mark";
            }
        }
    }
}